package com.wolfcode.appointment.service.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;

import com.wolfcode.appointment.domain.info.ServiceItemAuditInfo;
import com.wolfcode.appointment.domain.vo.BusServiceItemAuditVo;
import com.wolfcode.appointment.domain.vo.BusServiceItemVo;
import com.wolfcode.appointment.enums.AuditEnum;
import com.wolfcode.appointment.enums.BusCarPackageAuditEnum;
import com.wolfcode.appointment.enums.CarPackageEnum;
import com.wolfcode.appointment.enums.SaleEnum;
import com.wolfcode.audit.domain.BusCarPackageAudit;
import com.wolfcode.audit.domain.enums.BusPackageAuditEnum;
import com.wolfcode.audit.service.IBusCarPackageAuditService;
import com.wolfcode.common.core.domain.entity.SysUser;
import com.wolfcode.common.utils.ActivitiesUtils;
import com.wolfcode.common.utils.DateUtils;
import com.wolfcode.common.utils.SecurityUtils;
import com.wolfcode.flow.domain.BusBpmnInfo;
import com.wolfcode.flow.service.IBusBpmnInfoService;
import com.wolfcode.system.mapper.SysUserMapper;
import com.wolfcode.system.service.ISysUserService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wolfcode.appointment.mapper.BusServiceitemMapper;
import com.wolfcode.appointment.domain.BusServiceItem;
import com.wolfcode.appointment.service.IBusServiceitemService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * 服务项Service业务层处理
 *
 * @author wolfcode
 * @date 2022-11-23
 */
@Service
public class BusServiceitemServiceImpl implements IBusServiceitemService {
    @Autowired
    private BusServiceitemMapper busServiceitemMapper;
    @Autowired
    private IBusBpmnInfoService busBpmnInfoService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IBusCarPackageAuditService busCarPackageAuditService;

    @Autowired
    private SysUserMapper userMapper;

    /**
     * 查询服务项
     *
     * @param id 服务项主键
     * @return 服务项
     */
    @Override
    public BusServiceItem selectBusServiceitemById(Long id) {
        return busServiceitemMapper.selectBusServiceitemById(id);
    }

    /**
     * 查询服务项列表
     *
     * @param busServiceItem 服务项-
     * @return 服务项
     */
    @Override
    public List<BusServiceItem> selectBusServiceitemList(BusServiceItem busServiceItem) {
        return busServiceitemMapper.selectBusServiceitemList(busServiceItem);
    }

    /**
     * 新增服务项
     *
     * @param busServiceItemVo 服务项
     * @return 结果
     */
    @Override
    public int insertBusServiceitem(BusServiceItemVo busServiceItemVo) {
        Assert.notNull(busServiceItemVo, "非法参数");
        Assert.state(busServiceItemVo.getOriginalPrice()
                .compareTo(busServiceItemVo.getDiscountPrice()) >= 0, "折扣价不能大于原价");

        BusServiceItem busServiceItem = new BusServiceItem();
        BeanUtils.copyProperties(busServiceItemVo, busServiceItem);
        // 设置审核状态，判断是否是套餐
        boolean isCarPackage = busServiceItemVo.getCarPackage() == CarPackageEnum.YES.ordinal();
        busServiceItem.setAuditStatus(isCarPackage ? AuditEnum.INIT.ordinal() :
                AuditEnum.NO_AUDIT.ordinal());
        // 设置上下架状态，默认未上架
        busServiceItem.setSaleStatus(SaleEnum.NO.ordinal());
        busServiceItem.setCreateTime(DateUtils.getNowDate());
        return busServiceitemMapper.insertBusServiceitem(busServiceItem);
    }

    /**
     * 修改服务项
     *
     * @param busServiceItemVo 服务项
     * @return 结果
     */
    @Override
    public int updateBusServiceitem(BusServiceItemVo busServiceItemVo) {
        Assert.notNull(busServiceItemVo, "非法参数");
        Assert.state(busServiceItemVo.getOriginalPrice()
                .compareTo(busServiceItemVo.getDiscountPrice()) >= 0, "折扣价不能大于原价");
        // 1. 查询数据库是否存在该服务单项目 --前端没带，只能查数据库
        BusServiceItem busServiceItem = busServiceitemMapper
                .selectBusServiceitemById(busServiceItemVo.getId());
        // 除审核中状态，其他都可以编辑
        Assert.state(!(busServiceItem.getAuditStatus() == AuditEnum.AUDITING.ordinal()),
                "除审核中状态，其他都可以编辑");
        // 上架中的状态，也是不可以编辑的
        Assert.state(busServiceItem.getSaleStatus() == SaleEnum.NO.ordinal(),
                "上架中状态，不可以编辑");
        BusServiceItem serviceItem = new BusServiceItem();
        BeanUtils.copyProperties(busServiceItemVo, serviceItem);
        // 相当于重置
        // 设置审核状态，判断是否是套餐
        boolean isCarPackage = busServiceItemVo.getCarPackage() == CarPackageEnum.YES.ordinal();
        serviceItem.setAuditStatus(isCarPackage ? AuditEnum.INIT.ordinal() :
                AuditEnum.NO_AUDIT.ordinal());
        // 设置上下架状态，默认未上架
        serviceItem.setSaleStatus(SaleEnum.NO.ordinal());
        // 2 更新数据库
        return busServiceitemMapper.updateBusServiceitem(serviceItem);
    }

    /**
     * 批量删除服务项
     *
     * @param ids 需要删除的服务项主键
     * @return 结果
     */
    @Override
    public int deleteBusServiceitemByIds(Long[] ids) {
        return busServiceitemMapper.deleteBusServiceitemByIds(ids);
    }

    /**
     * 删除服务项信息
     *
     * @param id 服务项主键
     * @return 结果
     */
    @Override
    public int deleteBusServiceitemById(Long id) {
        return busServiceitemMapper.deleteBusServiceitemById(id);
    }

    /**
     * 上架
     *
     * @param id 服务项主键
     */
    @Override
    public void saleOn(Long id) {
        Assert.notNull(id, "非法参数");
        BusServiceItem busServiceItem = busServiceitemMapper.selectBusServiceitemById(id);
        // 已经是上架状态，不处理，直接返回
        if (busServiceItem.getAuditStatus() == SaleEnum.YES.ordinal()) return;
        // 必须是套餐并且审核通过后，或者无需审核的才能上架
//        boolean isCarPackage = busServiceItem.getCarPackage() == CarPackageEnum.YES.ordinal();
//        boolean pass = busServiceItem.getAuditStatus() == AuditEnum.PASS.ordinal();
        boolean pass = busServiceItem.getCarPackage() == CarPackageEnum.YES.ordinal()
                && busServiceItem.getAuditStatus() == AuditEnum.PASS.ordinal()
                // 无需审核的也可以上架
                || busServiceItem.getAuditStatus() == AuditEnum.NO_AUDIT.ordinal();
        Assert.state(pass, "必须是套餐并且审核通过后，或无需审核的才能上架");
        // 更新上架状态
        BusServiceItem serviceItem = new BusServiceItem();
        serviceItem.setId(id);
        serviceItem.setSaleStatus(SaleEnum.YES.ordinal());
        busServiceitemMapper.updateBusServiceitem(serviceItem);
    }

    /**
     * 原来是上架状态，点击按钮以后下架
     *
     * @param id 服务项主键
     */
    @Override
    public void saleOff(Long id) {
        Assert.notNull(id, "非法参数");
        BusServiceItem busServiceItem = new BusServiceItem();
        // tip: 不要忘记设置id
        busServiceItem.setId(id);
        busServiceItem.setSaleStatus(SaleEnum.NO.ordinal());
        busServiceitemMapper.updateBusServiceitem(busServiceItem);
    }

    /**
     * 发起审核
     * @param id
     * @return
     */
    @Override
    @Transactional
    public ServiceItemAuditInfo auditInfo(Long id) {
        // 构建Info返回
        // 1. 获取服务单项
        Assert.notNull(id, "非法参数");
        BusServiceItem busServiceItem = busServiceitemMapper.selectBusServiceitemById(id);
        Assert.notNull(busServiceItem, "该服务项不存在");
        // 在套餐，为上架，初始化，审批拒绝状态才可审核
        Assert.state(
                busServiceItem.getCarPackage() == CarPackageEnum.YES.ordinal(),
                "服务项必须是套餐才可审核");
        Assert.state(busServiceItem.getSaleStatus() == SaleEnum.NO.ordinal(),
                "未上架状态才可审核");
        Assert.state(busServiceItem.getAuditStatus() == AuditEnum.INIT.ordinal()
                        || busServiceItem.getAuditStatus() == AuditEnum.REJECT.ordinal(),
                "审批为初始化，或者拒绝状态才可审核");
        // 2 通过角色获取用户
        // 获取角色是店长的用户信息
        //List<SysUser> shopOwners = userMapper.selectUsersByRoleId(4L);
        List<SysUser> shopOwners = userService.queryByRoleKey("shopOwner");
        Assert.notNull(shopOwners, "角色为店长的用户不存在");

        // 3 假如符合业务，价格大于等于4000，查询财务角色信息
        BusBpmnInfo busBpmnInfo = busBpmnInfoService.getBpmnType(
                BusCarPackageAuditEnum.FLOW_AUDIT_TYPE.ordinal());
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(busBpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(busBpmnInfo.getVersion().intValue())
                .singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        System.out.println(bpmnModel);
        BigDecimal discountPrice = ActivitiesUtils.getGTEDiscountPrice(
                bpmnModel, busBpmnInfo.getProcessDefinitionKey());
        ServiceItemAuditInfo serviceItemAuditInfo = new ServiceItemAuditInfo();
        serviceItemAuditInfo.setServiceItem(busServiceItem);
        serviceItemAuditInfo.setShopOwners(shopOwners);
        serviceItemAuditInfo.setDiscountPrice(discountPrice);
        // 获取角色是财务的用户信息
        // List<SysUser> finances = userMapper.selectUsersByRoleId(5L);
        // 对比服务项的折扣价和流程定义的价格
        if (busServiceItem.getDiscountPrice().compareTo(discountPrice) >= 0) {
            List<SysUser> finances = userService.queryByRoleKey("financial");
            Assert.notNull(finances, "角色为财务的用户不存在");
            serviceItemAuditInfo.setFinances(finances);
        }
        return serviceItemAuditInfo;
    }

    /**
     * 开启审核
     *
     * @param auditVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startAudit(BusServiceItemAuditVo auditVo) {
        // 校验是否流程定义
        BusBpmnInfo busBpmnInfo = busBpmnInfoService.getBpmnType(
                BusCarPackageAuditEnum.FLOW_AUDIT_TYPE.ordinal());
        Assert.notNull(busBpmnInfo, "请先上传流程定义");
        // 获取服务单项
        BusServiceItem busServiceItem = busServiceitemMapper.selectBusServiceitemById(auditVo.getId());
        Assert.notNull(busServiceItem, "该服务单项不存在");
        //  在套餐，未上架，初始化，审批拒绝状态才可审核
        Assert.state(
                busServiceItem.getCarPackage() == CarPackageEnum.YES.ordinal(),
                "服务项必须是套餐才可审核");
        Assert.state(busServiceItem.getSaleStatus() == SaleEnum.NO.ordinal(),
                "未上架状态才可审核");
        Assert.state(busServiceItem.getAuditStatus() == AuditEnum.INIT.ordinal()
                        || busServiceItem.getAuditStatus() == AuditEnum.REJECT.ordinal(),
                "审批为初始化，或者拒绝状态才可审核");
        // 2. 开启套餐审核流程实例
        // 获取流程定义的key
        String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();
        // 业务标识BusinessKey(服务单项id)
        String BusinessKey = auditVo.getId().toString();
        // 存储流程定义变量
        HashMap<String, Object> params = new HashMap<>();
        params.put("shopOwnerId", auditVo.getShopOwnerId());
        if (auditVo.getFinanceId() != null) {
            params.put("financeId", auditVo.getFinanceId());
        }
        //  TODO 为什么 busServiceItem.getDiscountPrice().longValue()
        params.put("disCountPrice", busServiceItem.getDiscountPrice().longValue());
        // 开启流程实例
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey(processDefinitionKey, BusinessKey, params);
        // 保存审核套餐信息，更新状态
        // 封装CarPackageAudit对象
        BusCarPackageAudit audit = new BusCarPackageAudit();
        audit.setServiceItemId(busServiceItem.getId());
        audit.setServiceItemName(busServiceItem.getName());
        // 服务单项审核价格
        audit.setServiceItemPrice(busServiceItem.getDiscountPrice());
        audit.setServiceItemInfo(busServiceItem.getInfo());
        audit.setInfo(auditVo.getInfo());
        // 审核状态
        // 套餐审核状态（和服务单项的审核状态不通用）
        audit.setStatus(BusPackageAuditEnum.AUDITING.ordinal());
        audit.setCreatorId(SecurityUtils.getUserId().toString());
        audit.setCreateTime(DateUtils.getNowDate());
        audit.setInstanceId(processInstance.getId());

        busCarPackageAuditService.insertBusCarPackageAudit(audit);
        // 4 更新服务单项状态为审核中
        BusServiceItem serviceItem = new BusServiceItem();
        serviceItem.setId(busServiceItem.getId());
        // 服务单项的审核状态
        serviceItem.setAuditStatus(AuditEnum.AUDITING.ordinal());
        busServiceitemMapper.updateBusServiceitem(serviceItem);

    }
}
